#define MiX_DOMPARSER_CPP_

#include "DOM_Parser.h"

#include "Attribute.h"
#include "Element.h"

namespace MiX{
  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::parseAttribute(const attrmap_type& attr){
    string_type nm,ns;
    typename attrmap_type::const_iterator it = attr.begin();
    for( ;it!=attr.end();it++){
      size_t n =  it->first.find(xml_traits::colon());
      if( n==it->first.npos ) { nm = it->first; }
      else { 
	ns = it->first.substr( 0,n ); 
	nm = it->first.substr( n+1, it->first.npos); 
      }
      if( ns==xml_traits::str_xmlns() ) { // xmlns:hoge='URL'
	current_->declareNamespace(nm,it->second);
      } else if( ns==string_type() && nm==xml_traits::str_xmlns() ) { 
	// xmlns='URL'
	current_->declareNamespace(string_type(),it->second);
      } else { // hoge='Value'
	string_type url;
	if( current_->getType()==Node_Element ){
	  element_type& el = dynamic_cast<element_type&>(*current_);
	  if( ns.empty() ) url = el.getURI();
	  else {
	    url = el.queryURI(ns);
	  }
	}
	attribute_type* att=new attribute_type(nm,url,it->second);
	current_->addChild(att);
      }
    }
  }

  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::onXMLDeclaration(attrmap_type attr){
    typename attrmap_type::iterator it = attr.begin();
    typename attrmap_type::iterator last = attr.end();
    for( ;it!=last;it++){
      attribute_type* attr= new attribute_type(it->first,string_type(),it->second);
      current_->addChild(attr);
    }
  }
  
  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::onStart(string_type name,attrmap_type attr){
    string_type nm,ns,url;
    size_t n =  name.find(xml_traits::colon());
    if( n==name.npos ) { nm = name; }
    else { ns = name.substr( 0,n ); nm = name.substr( n+1, name.npos); }
        
    element_type* el = new element_type(nm);
    current_->addChild(el);
    current_ = el;
    parseAttribute( attr );
    el->setURL( el->queryURI(ns) );
  }
  
  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::onEnd(string_type name){
    current_ = &(current_->getParent());
  }
  
  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::onText(string_type text){
    text_type* t = new text_type(text);
    current_->addChild(t);
  }
  
  template <class charT,class char_traits,class xml_traits>
  void DOM_Parser<charT,char_traits,xml_traits>::onComment(string_type text){
    comment_type* com = new comment_type(text);
    current_->addChild(com);
  }

  template <class charT,class char_traits,class xml_traits>
  Document<charT,char_traits,xml_traits>* DOM_Parser<charT,char_traits,xml_traits>::parse(const charT* text){
    parser_.setEventHandler(this);
    document_type* doc = new document_type();
    current_ = doc;
    parser_.parse(text);
    return doc;
  }  

#ifdef MiX_HAS_BASIC_STREAM
  template <class charT,class char_traits,class xml_traits>
  Document<charT,char_traits,xml_traits>* DOM_Parser<charT,char_traits,xml_traits>::parse(std::basic_istream<charT,char_traits>& is){
    parser_.setEventHandler(this);
    document_type* doc = new document_type();
    current_ = doc;
    parser_.parse(is);
    return doc;
  }
#endif//MiX_HAS_BASIC_STREAM

#ifdef MiX_BACKWARD_COMPATIBILITY
  template <class charT,class char_traits,class xml_traits>
  Document<charT,char_traits,xml_traits>& DOM_Parser<charT,char_traits,xml_traits>::parse(const charT* text){
    parser_.setEventHandler(this);
    document_type* doc = new document_type();
    current_ = doc;
    parser_.parse(text);
    return *doc;
  }  
#ifdef MiX_HAS_BASIC_STREAM
  template <class charT,class char_traits,class xml_traits>
  Document<charT,char_traits,xml_traits>& DOM_Parser<charT,char_traits,xml_traits>::parse(std::basic_istream<charT,char_traits>& is){
    parser_.setEventHandler(this);
    document_type* doc = new document_type();
    current_ = doc;
    parser_.parse(is);
    return *doc;
  }
#endif//MiX_HAS_BASIC_STREAM
#endif//MiX_BACKWARD_COMPATIBILITY
}
